(($) => {
  const objectToArray = (obj) => {
    const arr = [];
    for (let n in obj) arr.push(obj[n]);
    return arr;
  };

  class DOM {
    constructor(ops) {
      if (ops) {
        for (let n in ops)
          switch (n) {
            case "router":
              this.$router = ops[n].router;
              this.$route = ops[n].route;
              break;
            case "use":
              this.useGroup(ops[n]);
              break;
            case "App":
              this.createApp(ops[n]);
              break;
            default:
              this.use(ops[n]);
              break;
          }
      }
      return this;
    }
    createApp(ops) {
      this.useOptions = { ...ops };
      for (let n in ops) {
        switch (n) {
          case "data":
            this.useOptions[n] = ops[n]();
            break;
          case "template":
            const res = ops[n]();
            this.template =
              typeof res === "string"
                ? /^(#|\.)/.test(res)
                  ? document.querySelector(res).content
                  : (function (dom) {
                      dom.innerHTML = res;
                      return dom.content;
                    })(document.createElement("template"))
                : res;
            break;
          default:
            //this[n] = { ...ops[n] };
            break;
        }
      }
      "components" in ops && this.useGroup(ops.components);
      return this;
    }
    ready(callback) {
      const that = this;
      const completed = () => {
        $.document.removeEventListener("DOMContentLoaded", completed);
        $.removeEventListener("load", completed);
        typeof callback == "function" && callback.call(that);
      };
      $.document.addEventListener("DOMContentLoaded", completed);
      $.addEventListener("load", completed);
      return this;
    }
    component(name, ops) {
      $.customElements.define(name, ops);
      return this;
    }
    useGroup(arr) {
      if (typeof arr === "object") {
        objectToArray(arr).forEach((item) => this.use(item));
      } else if (typeof arr === "function") {
        this.use(arr);
      }
      return this;
    }
    use(fn) {
      typeof fn === "function" && fn(this);
      return this;
    }
    render() {
      let id, template, callback;
      const args = arguments,
        len = args.length;
      if (len === 3) {
        id = args[0];
        template = args[1];
        callback = args[2];
      } else if (len == 2) {
        id = args[0];
        template = args[1];
        callback = null;
      } else if (len === 1) {
        id = args[0];
        template = null;
        callback = null;
      }

      const _renderTemplate = () => {
        template = template || this.template;
        if (template) {
          const temp = document.createElement("template");
          temp.innerHTML = template;
          const target = document.querySelector(id);
          target && target.append(temp.content.cloneNode(true));
        }
      };
      _renderTemplate();
      return this;
    }
  }
  $.DOM = DOM;
  typeof define === "function" &&
    define("VT", (requireVT, exports, module) => {
      exports.DOM = DOM;
    });
})(this);
